import { UnitType, BuildingType, PlayerType, TildeType } from '../../../battle/Enums';
import { resources, SpriteAtlas, SpriteFrame, Prefab } from 'cc';
import { LOG } from '../../../ConsoleLogCtrl';

/**
 * 资源配置接口
 */
export interface SpriteConfig {
    /** 精灵帧路径 */
    path: string;
    /** 描述 */
    description?: string;
}

export const SpriteAtlasPath = {
    Building : 'ui/ui_building',
    soldier : 'ui/npc/soldier',
    collect : 'ui/npc/collect',
    doctor : 'ui/npc/doctor',
    archer : 'ui/npc/archer',
    worker : 'ui/npc/worker',
    icons: 'ui/npc/npc_icons',
    uiPanel: 'ui/ui_Panel',
    uiBoom: 'ui/ui_boom',
}

export const SpriteTypePath = {
    base : 'base',  //基地
    tower : 'tower', //防御塔
    wall : 'wall',  //城墙
    hill : 'hill',  //山丘
    river : 'river',  //河流
    gold : 'gold',  //黄金
    wood : 'wood',  //木材
    stone : 'stone',  //石材
    energy : 'energy',  //能源
}

/**
 * 建筑资源配置接口
 */
export interface BuildingSpriteConfig {
    [PlayerType.PLAYER1]: {
        [BuildingType.base]: SpriteConfig;
        [BuildingType.tower]: SpriteConfig;
    };
    [PlayerType.PLAYER2]: {
        [BuildingType.base]: SpriteConfig;
        [BuildingType.tower]: SpriteConfig;
    };
}

/**
 * 地形资源配置接口
 */
export interface TerrainSpriteConfig {
    [TildeType.flat]: SpriteConfig;
    [TildeType.hill]: SpriteConfig;
    [TildeType.river]: SpriteConfig;
    [TildeType.gold]: SpriteConfig;
    [TildeType.energy]: SpriteConfig;
    [TildeType.wood]: SpriteConfig;
    [TildeType.stone]: SpriteConfig;
}

/**
 * 资源配置类
 * 统一管理游戏中所有精灵帧资源路径
 */
export class ResourceLoadManager {
    /**
     * 图集缓存
     */
    private static atlasCache: Map<string, SpriteAtlas> = new Map();

    /**
     * 预制体缓存
     */
    private static prefabCache: Map<string, Prefab> = new Map();

    /**
     * 建筑精灵帧配置
     */
    public static readonly BUILDING_SPRITES: BuildingSpriteConfig = {
        [PlayerType.PLAYER1]: {
            [BuildingType.base]: {
                path: 'base1',
                description: '玩家1基地'
            },
            [BuildingType.tower]: {
                path: 'tower1_1',
                description: '玩家1防御塔'
            }
        },
        [PlayerType.PLAYER2]: {
            [BuildingType.base]: {
                path: 'base2',
                description: '玩家2基地'
            },
            [BuildingType.tower]: {
                path: 'tower2_1',
                description: '玩家2防御塔'
            }
        }
    };

    /**
     * 地形精灵帧配置
     */
    public static readonly TERRAIN_SPRITES: TerrainSpriteConfig = {
        [TildeType.flat]: {
            path: 'plain',
            description: '平地'
        },
        [TildeType.hill]: {
            path: 'stone',
            description: '山丘'
        },
        [TildeType.river]: {
            path: 'river',
            description: '河流'
        },
        [TildeType.gold]: {
            path: 'buildingType2',
            description: '黄金'
        },
        [TildeType.energy]: {
            path: 'energy',
            description: '能源'
        },
        [TildeType.wood]: {
            path: 'wood',
            description: '木材'
        },
        [TildeType.stone]: {
            path: 'stone_resource',
            description: '石材'
        }
    };

    /**
     * 获取单位精灵帧
     * @param unitType 单位类型
     * @returns 精灵帧对象或null
     */
    public static getUnitSpriteFrame(unitType: UnitType, playerType: PlayerType): SpriteFrame | null {

        const key = this.getUnitTypeforPath(unitType)
        // 从缓存中获取NPC图集
        const npcAtlas = this.atlasCache.get(key);
        if (!npcAtlas) {
            LOG.warn('NPC图集未加载，请先调用loadNpcSpritesAtlas方法');
            return null;
        }
        const cType = this.getCTypeforPlayer(playerType);
        const uType = this.getUnitPrefixType(unitType);
        // 根据单位类型计算NPC索引
        const spriteName = `${uType}_${cType}_move_down_1`;

        // 从图集中获取精灵帧
        const spriteFrame = npcAtlas.getSpriteFrame(spriteName);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spriteName}`);
            return null;
        }
        return spriteFrame;
    }

    /**
     * 获取单位精灵帧
     * @param unitType 单位类型
     * @returns 精灵帧对象或null
     */
    public static getUnitSpriteFrameForName(unitType: UnitType,spriteName:string): SpriteFrame | null {

        const key = this.getUnitTypeforPath(unitType)
        // 从缓存中获取NPC图集
        const npcAtlas = this.atlasCache.get(key);
        if (!npcAtlas) {
            LOG.warn('NPC图集未加载，请先调用loadNpcSpritesAtlas方法');
            return null;
        }
        // 从图集中获取精灵帧
        const spriteFrame = npcAtlas.getSpriteFrame(spriteName);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spriteName}`);
            return null;
        }
        return spriteFrame;
    }

    /**
     * 获取单位精灵帧
     * @param unitType 单位类型
     * @returns 精灵帧对象或null
     */
    public static getUnitIcon(unitType: UnitType, playerType: PlayerType): SpriteFrame | null {
        // 从缓存中获取NPC图集
        const npcAtlas = this.atlasCache.get(SpriteAtlasPath.icons);
        if (!npcAtlas) {
            LOG.warn('NPC图集未加载，请先调用loadNpcSpritesAtlas方法');
            return null;
        }
        const cType = this.getCTypeforPlayer(playerType);
        const uType = this.getUnitPrefixType(unitType);
        // 根据单位类型计算NPC索引
        const spriteName = `${uType}_${cType}`;

        // 从图集中获取精灵帧
        const spriteFrame = npcAtlas.getSpriteFrame(spriteName);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spriteName}`);
            return null;
        }
        return spriteFrame;
    }

    /**
     * 获取建筑精灵帧路径
     * @param buildingType 建筑类型
     * @param playerType 玩家类型
     * @returns 精灵帧路径
     */
    public static getBuildingSpriteFrame(buildingType: BuildingType, playerType: PlayerType):  SpriteFrame | null {
        let spritePath = `${this.getBuildingTypePath(buildingType)}_${this.getCTypeforPlayer(playerType)}`; // 默认返回玩家1基地
        const buildingAtlas = this.atlasCache.get(SpriteAtlasPath.Building);
        if (!buildingAtlas) {
            LOG.warn('建筑图集未加载，请先调用loadNpcSpritesAtlas方法');
            return null;
        }

        // 从图集中获取精灵帧
        const spriteFrame = buildingAtlas.getSpriteFrame(spritePath);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spritePath}`);
            return null;
        }

        return spriteFrame;
    }

    /**
     * 获取UI面板精灵帧
     * @param panelType UI面板类型
     * @returns 精灵帧对象或null
     */
    public static getUIPanelSpriteFrame(spritePath:string): SpriteFrame | null {
        const uiPanelAtlas = this.atlasCache.get(SpriteAtlasPath.uiPanel);
        if (!uiPanelAtlas) {
            LOG.warn('UI面板图集未加载，请先调用loadUIPanelAtlas方法');
            return null;
        }

        // 从图集中获取精灵帧
        const spriteFrame = uiPanelAtlas.getSpriteFrame(spritePath);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spritePath}`);
            return null;
        }

        return spriteFrame;
    }

     /**
     * 获取UI面板精灵帧
     * @param atlasPath 图集路径
     * @param spritePath 资源名
     * @returns 精灵帧对象或null
     */
    public static getSpriteFrameForAtlasPath(atlasPath:string, spritePath:string): SpriteFrame | null {
        const uiPanelAtlas = this.atlasCache.get(atlasPath);
        if (!uiPanelAtlas) {
            LOG.warn('图集未加载，请先调用loadUIPanelAtlas方法');
            return null;
        }

        // 从图集中获取精灵帧
        const spriteFrame = uiPanelAtlas.getSpriteFrame(spritePath);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spritePath}`);
            return null;
        }

        return spriteFrame;
    }

    /**
     * 获取地形精灵帧
     * @param tildeType 地形类型
     * @returns 精灵帧对象或null
     */
    public static getTerrainSpriteFrame(tildeType: TildeType): SpriteFrame | null {
        const spritePath = `${this.getTerrainTypePath(tildeType)}`;
        const terrainAtlas = this.atlasCache.get(SpriteAtlasPath.Building);
        if (!terrainAtlas) {
            LOG.warn('地形图集未加载，请先调用loadBuildingAtlas方法');
            return null;
        }

        // 从图集中获取精灵帧
        const spriteFrame = terrainAtlas.getSpriteFrame(spritePath);
        if (!spriteFrame) {
            LOG.warn(`未找到精灵帧: ${spritePath}`);
            return null;
        }

        return spriteFrame;
    }


    /**
     * 加载NpcSprites图集
     * @param callback 加载完成回调函数
     */
    public static loadNpcSpritesAtlas( key:string ,callback: (err: Error | null, atlas?: SpriteAtlas) => void): void {
        // 检查缓存
        const cachedAtlas = this.atlasCache.get(SpriteAtlasPath[key]);
        if (cachedAtlas) {
            LOG.log('从缓存获取NpcSprites图集');
            callback(null, cachedAtlas);
            return;
        }

        resources.load(SpriteAtlasPath[key], SpriteAtlas, (err, atlas) => {
            if (err) {
                LOG.error('加载NpcSprites图集失败:', err);
                callback(err);
                return;
            }

            // 缓存图集
            this.atlasCache.set(SpriteAtlasPath[key], atlas);
            LOG.log('NpcSprites图集加载成功并已缓存');
            callback(null, atlas);
        });
    }

    /**
     * 加载ui_building图集
     * @param callback 加载完成回调函数
     */
    public static loadBuildingAtlas(callback: (err: Error | null, atlas?: SpriteAtlas) => void): void {
        // 检查缓存
        const cachedAtlas = this.atlasCache.get(SpriteAtlasPath.Building);
        if (cachedAtlas) {
            LOG.log('从缓存获取ui_building图集');
            callback(null, cachedAtlas);
            return;
        }

        resources.load(SpriteAtlasPath.Building, SpriteAtlas, (err, atlas) => {
            if (err) {
                LOG.error('加载ui_building图集失败:', err);
                callback(err);
                return;
            }

            // 缓存图集
            this.atlasCache.set(SpriteAtlasPath.Building, atlas);
            LOG.log('ui_building图集加载成功并已缓存');
            callback(null, atlas);
        });
    }

    /**
     * 加载ui_panel图集
     * @param callback 加载完成回调函数
     */
    public static loadUIPanelAtlas(callback: (err: Error | null, atlas?: SpriteAtlas) => void): void {
        // 检查缓存
        const cachedAtlas = this.atlasCache.get(SpriteAtlasPath.uiPanel);
        if (cachedAtlas) {
            LOG.log('从缓存获取ui_panel图集');
            callback(null, cachedAtlas);
            return;
        }

        resources.load(SpriteAtlasPath.uiPanel, SpriteAtlas, (err, atlas) => {
            if (err) {
                LOG.error('加载ui_panel图集失败:', err);
                callback(err);
                return;
            }

            // 缓存图集
            this.atlasCache.set(SpriteAtlasPath.uiPanel, atlas);
            LOG.log('ui_panel图集加载成功并已缓存');
            callback(null, atlas);
        });
    }

    /**
     * 预加载所有图集资源
     * @param callback 加载完成回调函数
     */
    public static preloadAllAtlases(callback: (err: Error | null, results?: {}) => void): void {
        let loadedCount = 0;
        let totalCount = 2;
        let hasError = false;
        const results = {};

        const checkComplete = () => {
            loadedCount++;
            if (loadedCount === Object.keys(SpriteAtlasPath).length && !hasError) {
                LOG.log('所有图集预加载完成');
                callback(null, results);
            }
        };

        for (const key in SpriteAtlasPath) {
            resources.load(SpriteAtlasPath[key], SpriteAtlas, (err, atlas) => {
                if (err) {
                    hasError = true;
                    callback(err);
                    return;
                }
                this.atlasCache.set(SpriteAtlasPath[key], atlas);
                checkComplete();
            });
        }
    }

    /**
     * 从缓存中获取图集
     * @param atlasPath 图集路径
     * @returns 缓存的图集或undefined
     */
    public static getCachedAtlas(atlasPath: string): SpriteAtlas | undefined {
        return this.atlasCache.get(atlasPath);
    }

    /**
     * 清除图集缓存
     * @param atlasPath 可选的图集路径，如果不提供则清除所有缓存
     */
    public static clearAtlasCache(atlasPath?: string): void {
        if (atlasPath) {
            this.atlasCache.delete(atlasPath);
            LOG.log(`已清除图集缓存: ${atlasPath}`);
        } else {
            this.atlasCache.clear();
            LOG.log('已清除所有图集缓存');
        }
    }

    /**
     * 获取缓存状态信息
     * @returns 缓存状态信息
     */
    public static getCacheInfo(): { size: number; paths: string[] } {
        return {
            size: this.atlasCache.size,
            paths: Array.from(this.atlasCache.keys())
        };
    }

    /**
     * 获取单位类型对应的图集路径key
     * @param unitType 单位类型
     * @returns 图集路径
     */
    public static getUnitTypeforPath(unitType:UnitType):string{

        let key = SpriteAtlasPath.soldier;
        switch(unitType){
            case UnitType.soldier:
                key = SpriteAtlasPath.soldier;
                break;
            case UnitType.collect:
                key = SpriteAtlasPath.collect;
                break;
            case UnitType.doctor:
                key = SpriteAtlasPath.doctor;
                break;
            case UnitType.archer:
                key = SpriteAtlasPath.archer;
                break;
            case UnitType.worker:
                key = SpriteAtlasPath.worker;
                break;
        }
        LOG.log(`getUnitTypeforPath:${key}`);
        return key;
    }

    /**
     * 获取玩家类型对应的颜色
     * @param playerType 玩家类型
     * @returns
     */
    public static getCTypeforPlayer(playerType:PlayerType):string{
        let colorType = 'red';
        if (playerType === PlayerType.PLAYER2) {
            colorType =  'blue';
        }
        return colorType;
    }

    /**
     * 获取单位类型对应的前缀
    */
    public static getUnitPrefixType(unitType:UnitType):string{
        let prefix = 'soldier';
        switch(unitType){
            case UnitType.soldier:
                prefix = 'soldier';
                break;
            case UnitType.collect:
                prefix = 'collect';
                break;
            case UnitType.doctor:
                prefix = 'doctor';
                break;
            case UnitType.archer:
                prefix = 'archer';
                break;
            case UnitType.worker:
                prefix = 'worker';
                break;
        }
        return prefix;
    }

    /**
     * 获取地形类型对应的路径
     * @param tildeType 地形类型
     * @returns 对应的路径字符串
     */
    public static getTerrainTypePath(tildeType: TildeType): string {
        let path = 'base';
        switch(tildeType) {
            case TildeType.flat:
                path = SpriteTypePath.base;
                break;
            case TildeType.hill:
                path = SpriteTypePath.hill;
                break;
            case TildeType.river:
                path = SpriteTypePath.river;
                break;
            case TildeType.gold:
                path = SpriteTypePath.gold;
                break;
            case TildeType.energy:
                path = SpriteTypePath.energy;
                break;
            case TildeType.wood:
                path = SpriteTypePath.wood;
                break;
            case TildeType.stone:
                path = SpriteTypePath.stone;
                break;
        }
        return path;
    }

        /**
     * 获取地形类型对应的路径
     * @param tildeType 地形类型
     * @returns 对应的路径字符串
     */
    public static getBuildingTypePath(buildingType: BuildingType): string {
        let path = 'base';
        switch(buildingType) {
            case BuildingType.base:
                path = SpriteTypePath.base;
                break;
            case BuildingType.tower:
                path = SpriteTypePath.tower;
                break;
            case BuildingType.wall:
                path = SpriteTypePath.wall;
                break;
        }
        return path;
    }

    /**
     * 加载预制体
     * @param prefabName 预制体名称（路径）
     * @param callback 加载完成回调函数
     */
    public static loadPrefab(prefabName: string, callback: (err: Error | null, prefab?: Prefab) => void): void {
        // 检查缓存
        const cachedPrefab = this.prefabCache.get(prefabName);
        if (cachedPrefab) {
            LOG.log(`从缓存获取预制体: ${prefabName}`);
            callback(null, cachedPrefab);
            return;
        }

        // 从资源管理器加载预制体
        resources.load(prefabName, Prefab, (err, prefab) => {
            if (err) {
                LOG.error(`加载预制体失败: ${prefabName}`, err);
                callback(err);
                return;
            }

            // 缓存预制体
            this.prefabCache.set(prefabName, prefab);
            LOG.log(`预制体加载成功并已缓存: ${prefabName}`);
            callback(null, prefab);
        });
    }

    /**
     * 从缓存中获取预制体
     * @param prefabName 预制体名称
     * @returns 缓存的预制体或undefined
     */
    public static getCachedPrefab(prefabName: string): Prefab | undefined {
        return this.prefabCache.get(prefabName);
    }

    /**
     * 清除预制体缓存
     * @param prefabName 可选的预制体名称，如果不提供则清除所有预制体缓存
     */
    public static clearPrefabCache(prefabName?: string): void {
        if (prefabName) {
            this.prefabCache.delete(prefabName);
            LOG.log(`已清除预制体缓存: ${prefabName}`);
        } else {
            this.prefabCache.clear();
            LOG.log('已清除所有预制体缓存');
        }
    }

    /**
     * 获取预制体缓存状态信息
     * @returns 预制体缓存状态信息
     */
    public static getPrefabCacheInfo(): { size: number; names: string[] } {
        return {
            size: this.prefabCache.size,
            names: Array.from(this.prefabCache.keys())
        };
    }

}